package com.duobaoyu.dby.supply.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.lang.Tuple;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.order.OrderStatusEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.order.OrderTypeEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.product.ProductTypeEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.refund.AfterSaleStatusEnum;
import com.duobaoyu.dby.channel.boundary.bean.order.param.LogisticQueryParam;
import com.duobaoyu.dby.channel.common.util.SupplyCollectionUtils;
import com.duobaoyu.dby.common.core.constant.CommonConstants;
import com.duobaoyu.dby.common.core.constant.StringPool;
import com.duobaoyu.dby.common.mybatis.util.EnumUtils;
import com.duobaoyu.dby.supply.admin.service.AdminOrderBizService;
import com.duobaoyu.dby.supply.biz.client.boundary.order.OrderBoundaryClient;
import com.duobaoyu.dby.supply.biz.client.boundary.order.bean.bo.*;
import com.duobaoyu.dby.supply.biz.client.resource.ResourceBusinessConfigAdminClient;
import com.duobaoyu.dby.supply.biz.client.resource.ResourceTaskAsyncAdminClient;
import com.duobaoyu.dby.supply.biz.client.resource.bean.vo.BusinessConfigVO;
import com.duobaoyu.dby.supply.biz.constant.OperateSourceConstants;
import com.duobaoyu.dby.supply.biz.constant.OrderOperateConstants;
import com.duobaoyu.dby.supply.biz.converter.OrderConverter;
import com.duobaoyu.dby.supply.biz.enums.*;
import com.duobaoyu.dby.supply.biz.producer.SupplyChainDelayMessageProducer;
import com.duobaoyu.dby.supply.biz.producer.SupplyChainMQProducer;
import com.duobaoyu.dby.supply.biz.service.config.OperationLogService;
import com.duobaoyu.dby.supply.biz.service.config.PreWarningConfigService;
import com.duobaoyu.dby.supply.biz.service.order.OrderProductService;
import com.duobaoyu.dby.supply.biz.service.order.OrderRepairService;
import com.duobaoyu.dby.supply.biz.service.order.OrderService;
import com.duobaoyu.dby.supply.biz.service.refund.AfterSaleService;
import com.duobaoyu.dby.supply.common.biz.bo.order.OrderListBO;
import com.duobaoyu.dby.supply.common.biz.bo.order.OrderRepairBO;
import com.duobaoyu.dby.supply.common.biz.bo.order.OrderStatusCheckBO;
import com.duobaoyu.dby.supply.common.biz.bo.order.UpdateOrderRepairBO;
import com.duobaoyu.dby.supply.common.biz.bo.refund.AfterSaleItemOutBO;
import com.duobaoyu.dby.supply.common.biz.bo.refund.AfterSaleItemQuery;
import com.duobaoyu.dby.supply.common.biz.dto.config.OperationLogSaveDTO;
import com.duobaoyu.dby.supply.common.biz.dto.config.PreWarningConditionDTO;
import com.duobaoyu.dby.supply.common.biz.dto.order.*;
import com.duobaoyu.dby.supply.common.biz.vo.order.*;
import com.duobaoyu.dby.supply.core.common.exception.CustomAssert;
import com.duobaoyu.dby.supply.core.task.bean.exporttask.ExportParam;
import com.duobaoyu.dby.supply.core.task.enums.BizTaskTypeEnum;
import com.duobaoyu.dby.supply.db.util.OperateAuthUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.Diff;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chenms
 * @date 2023/10/16 3:33 PM
 */
@Service
@RequiredArgsConstructor
public class AdminOrderBizServiceImpl implements AdminOrderBizService {
	private final OrderService orderService;
	private final OrderConverter orderConverter;
	private final OperationLogService operationLogService;
	private final AfterSaleService afterSaleService;
	private final ResourceBusinessConfigAdminClient resourceBusinessConfigAdminClient;
	private final OrderRepairService orderRepairService;
	private final OrderBoundaryClient orderBoundaryClient;
	private final OrderProductService orderProductService;
	private final SupplyChainMQProducer supplyChainMQProducer;
	private final PreWarningConfigService preWarningConfigService;
	private final ResourceTaskAsyncAdminClient resourceTaskAsyncAdminClient;
	private final SupplyChainDelayMessageProducer supplyChainDelayMessageProducer;

	@Override
	public Page<OrderPageVO> pageOrderList(OrderPageDTO orderPage) {
		if (Objects.nonNull(orderPage.getPreWarningStrategyId())) {
			PreWarningConditionDTO preWarningCondition = preWarningConfigService.getPreWarningCondition(orderPage.getPreWarningStrategyId());
			orderPage.setPreWarningCondition(preWarningCondition);
		}

		IPage<OrderListBO> orderListPage = orderService.queryOrderPage(orderPage);
		//组装返回结果
		Page<OrderPageVO> resultPage = new Page<>();
		if (Objects.nonNull(orderListPage) && CollectionUtils.isNotEmpty(orderListPage.getRecords())) {
			List<OrderPageVO> orderPageList = new ArrayList<>(orderListPage.getRecords().size());
			for (OrderListBO orderList : orderListPage.getRecords()) {
				OrderPageVO orderPageVo = new OrderPageVO();
				String showServerName = StringPool.EMPTY;
				if (StringUtils.isNotBlank(orderList.getShowServerName())) {
					showServerName = resourceBusinessConfigAdminClient.getBizCode(orderList.getShowServerName()).getBizDescribe();
				}
				orderPageVo.setChannelCode(orderList.getChannelCode());
				orderPageVo.setOrderSn(orderList.getOrderSn());
				orderPageVo.setBizTradeSn(orderList.getBizTradeSn());
				orderPageVo.setChannelOrderSn(orderList.getChannelOrderSn());
				orderPageVo.setSupplyTradeSn(orderList.getSupplyTradeSn());
				orderPageVo.setMchId(orderList.getMchId());
				orderPageVo.setSkuCode(orderList.getSkuCode());
				orderPageVo.setSkuName(orderList.getSkuName());
				orderPageVo.setSkuPic(orderList.getSkuPic());
				orderPageVo.setSkuNum(orderList.getSkuNum());
				orderPageVo.setTotalPlatformSellPrice(orderList.getPlatformSellPrice().multiply(BigDecimal.valueOf(orderList.getSkuNum())));
				orderPageVo.setTotalPlatformPrice(orderList.getPlatformPrice().multiply(BigDecimal.valueOf(orderList.getSkuNum())));
				orderPageVo.setIcon(ChannelCodeEnum.getChannelCodeEnumByCode(orderList.getChannelCode()).getLogo());
				orderPageVo.setShowServerName(showServerName);
				orderPageVo.setOrderStatus(orderList.getOrderStatus());
				OrderStatusEnum orderStatusEnum = OrderStatusEnum.getOrderSubStatusEnum(orderPageVo.getOrderStatus());
				orderPageVo.setOrderStatusDesc(orderStatusEnum.getDescribe());
				orderPageVo.setConsigneeName(orderList.getRecipientName());
				orderPageVo.setConsigneePhone(orderList.getRecipientMobile());
				orderPageVo.setOrderRemark(orderList.getOrderRemark());
				orderPageVo.setOperateRemark(orderList.getOperateRemark());
				orderPageVo.setRechargeAccount(StringUtils.isBlank(orderList.getRechargeAccount()) ? StringPool.DASHED : orderList.getRechargeAccount());
				orderPageVo.setCreateTime(orderList.getCreateTime());
				orderPageList.add(orderPageVo);
			}
			resultPage.setCurrent(orderListPage.getCurrent());
			resultPage.setSize(orderListPage.getSize());
			resultPage.setTotal(orderListPage.getTotal());
			resultPage.setRecords(orderPageList);
		}
		return resultPage;
	}

	@Override
	public boolean saveOperateRemark(OperateRemarkDTO operateRemark) {
		return orderProductService.saveOperateRemark(operateRemark);
	}

	@Override
	public Boolean export(ExportParam<OrderPageDTO> param) {
		resourceTaskAsyncAdminClient.asyncExport(ExportParam.<String>builder()
				.exportDataType(BizTaskTypeEnum.SUPPLY_CHAIN_PURCHASE_ORDER.getValue())
				.searchParameter(JSON.toJSONString(param.getSearchParameter(), SerializerFeature.WriteMapNullValue))
				.exportedFieldsParameter(param.getExportedFieldsParameter())
				.build());
		return Boolean.TRUE;
	}

	@Override
	public OrderSubDetailVO orderSubDetail(String orderSn) {
		OrderQueryInBO orderQueryIn = new OrderQueryInBO();
		orderQueryIn.setOrderSnList(Collections.singletonList(orderSn));
		orderQueryIn.setReturnProduct(Boolean.TRUE);
		orderQueryIn.setReturnConsignee(Boolean.TRUE);
		List<OrderBO> orderList = orderService.list(orderQueryIn);
		if (CollectionUtils.isEmpty(orderList)) {
			return null;
		}
		OrderBO orderBo = SupplyCollectionUtils.getSingleDataFirst(orderList);
		if (Objects.isNull(orderBo)) {
			return null;
		}
		//订单信息
		OrderSubDetailVO.OrderInfo orderInfo = this.buildSubDetailOrderInfo(orderBo);
		//收货信息
		OrderSubDetailVO.Consignee consignee = this.buildSubDetailConsignee(orderBo.getOrderAddress());
		//商品信息
		List<OrderSubDetailVO.ProductInfo> productInfoList = this.buildSubDetailProductInfo(orderBo);
		//组装返回结果
		OrderSubDetailVO orderSubDetail = new OrderSubDetailVO();
		orderSubDetail.setOrderInfo(orderInfo);
		orderSubDetail.setConsignee(consignee);
		orderSubDetail.setProductInfoList(productInfoList);
		return orderSubDetail;
	}

	/**
	 * 组装子单详情-->订单信息
	 */
	private OrderSubDetailVO.OrderInfo buildSubDetailOrderInfo(OrderBO order) {
		OrderSubDetailVO.OrderInfo orderInfo = new OrderSubDetailVO.OrderInfo();
		//订单信息
		orderInfo.setSupplyTradeSn(order.getSupplyTradeSn());
		orderInfo.setBizTradeSn(order.getBizTradeSn());
		orderInfo.setOrderSn(order.getOrderSn());
		orderInfo.setOrderParentSn(order.getOrderParentSn());
		orderInfo.setChannelOrderSn(order.getChannelOrderSn());
		orderInfo.setChannelOrderParentSn(order.getChannelOrderParentSn());
		orderInfo.setChannelTradeOrderSn(order.getChannelTradeOrderSn());
		orderInfo.setChannelCode(order.getChannelCode());
		ChannelCodeEnum channelCodeEnum = ChannelCodeEnum.getChannelCodeEnumByCode(order.getChannelCode());
		if (Objects.nonNull(channelCodeEnum)) {
			orderInfo.setChannelDesc(channelCodeEnum.getDescribe());
		}
		orderInfo.setOrderType(order.getOrderType());
		//业务来源
		BusinessConfigVO bizConfig = resourceBusinessConfigAdminClient.getBizCode(order.getShowServerName());
		if (Objects.nonNull(bizConfig)) {
			orderInfo.setShowServerName(bizConfig.getBizDescribe());
		}
		orderInfo.setMchId(order.getMchId());
		orderInfo.setUserId(order.getUserId());
		orderInfo.setOrderStatus(order.getOrderStatus());
		orderInfo.setOrderStatusDesc(OrderStatusEnum.getOrderSubStatusDesc(order.getOrderStatus()));
		if (EnumUtils.eq(OrderStatusEnum.CANCEL, order.getOrderStatus())) {
			orderInfo.setReason(order.getCancelReason());
		} else if (EnumUtils.eq(OrderStatusEnum.FAILURE, order.getOrderStatus())) {
			orderInfo.setReason(order.getFailReason());
		}
		orderInfo.setCreateTime(order.getCreateTime());
		orderInfo.setUpdateTime(order.getUpdateTime());

		boolean cancelOrderFlag = EnumUtils.eq(OrderStatusEnum.WAIT_SHIP, order.getOrderStatus());
		orderInfo.setCancelOrderFlag(cancelOrderFlag ? CommonConstants.ONE : CommonConstants.ZERO);
		return orderInfo;
	}

	/**
	 * 组装子单详情-->收货信息
	 */
	private OrderSubDetailVO.Consignee buildSubDetailConsignee(OrderAddressBO orderAddress) {
		if (Objects.isNull(orderAddress)) {
			return null;
		}
		OrderSubDetailVO.Consignee consignee = new OrderSubDetailVO.Consignee();
		consignee.setConsigneeName(orderAddress.getRecipientName());
		consignee.setConsigneePhone(orderAddress.getRecipientMobile());
		consignee.setConsigneeIdCardNum(orderAddress.getRecipientIdCardNum());
		consignee.setConsigneeProvinceName(orderAddress.getProvinceName());
		consignee.setConsigneeCityName(orderAddress.getCityName());
		consignee.setConsigneeCountyName(orderAddress.getCountyName());
		consignee.setConsigneeTownName(orderAddress.getTownName());
		consignee.setConsigneeAddress(orderAddress.getAddress());
		return consignee;
	}

	/**
	 * 组装子单详情-->商品信息
	 */
	private List<OrderSubDetailVO.ProductInfo> buildSubDetailProductInfo(OrderBO order) {
		List<OrderProductBO> orderProductList = order.getOrderProductList();
		Map<String, Tuple> channelSkuRefundMap = Maps.newHashMap();
		//实物订单才存在售后场景
		if (EnumUtils.eq(OrderTypeEnum.REAL_ORDER, order.getOrderType())) {
			channelSkuRefundMap = this.getChannelSkuRefundInfo(orderProductList);
		}
		//商品信息
		List<OrderSubDetailVO.ProductInfo> productInfoList = Lists.newArrayList();
		for (OrderProductBO orderProduct : orderProductList) {
			OrderSubDetailVO.ProductInfo productInfo = new OrderSubDetailVO.ProductInfo();
			productInfo.setOrderSn(orderProduct.getOrderSn());
			productInfo.setSkuCode(orderProduct.getSkuCode());
			productInfo.setSkuName(orderProduct.getSkuName());
			productInfo.setSkuPic(orderProduct.getSkuPic());
			productInfo.setSkuNum(orderProduct.getSkuNum());
			productInfo.setSaleAttributes(JSON.parseObject(orderProduct.getSaleAttributes(), new TypeReference<List<SaleAttributeVO>>() {
			}));
			productInfo.setPlatformPrice(orderProduct.getPlatformPrice());
			productInfo.setTotalPlatformPrice(orderProduct.getPlatformPrice().multiply(BigDecimal.valueOf(orderProduct.getSkuNum())));
			productInfo.setPlatformSellPrice(orderProduct.getPlatformSellPrice());
			productInfo.setTotalPlatformSellPrice(orderProduct.getPlatformSellPrice().multiply(BigDecimal.valueOf(orderProduct.getSkuNum())));
			productInfo.setProductType(ProductTypeEnum.getProductTypeEnum(orderProduct.getProductType()).getDescribe());
			productInfo.setRechargeAccount(order.getRechargeAccount());
			//productInfo.setStatus(orderProductBo.getStatus().equals(OrderStatusEnum.CANCEL.getValue()) ? "已关闭" : "正常");
			Tuple refundTuple = channelSkuRefundMap.get(orderProduct.getSkuCode());
			if (Objects.nonNull(refundTuple)) {
				productInfo.setTotalChannelRefundAmount(refundTuple.get(CommonConstants.ZERO));
				productInfo.setExistsAfterSaleApply(Boolean.TRUE);
			} else {
				productInfo.setTotalChannelRefundAmount(BigDecimal.ZERO);
				productInfo.setExistsAfterSaleApply(Boolean.FALSE);
			}
			OrderProductBO.OrderExtendParam paramExtend = orderProduct.getParamExtend();
			if (Objects.nonNull(paramExtend) && Objects.nonNull(paramExtend.getPhoneOperator())) {
				productInfo.setPhoneOperator(paramExtend.getPhoneOperator().getOperatorName());
				String phoneAddress = StrUtil.concat(Boolean.TRUE, paramExtend.getPhoneOperator().getProvinceName(), paramExtend.getPhoneOperator().getCityName());
				productInfo.setPhoneAddress(phoneAddress);
			}
			productInfoList.add(productInfo);
		}
		return productInfoList;
	}

	/**
	 * 获取渠道订单商品退款信息
	 * Tuple 第1个渠道退款金额,第二个渠道退款运费
	 */
	private Map<String, Tuple> getChannelSkuRefundInfo(List<OrderProductBO> orderProductList) {
		List<Integer> refundCompleteStatusList = Lists.newArrayList(AfterSaleStatusEnum.TO_BE_CONFIRMED_BY_USER.getValue(), AfterSaleStatusEnum.COMPLETED.getValue());
		List<String> orderSnList = orderProductList.stream().map(OrderProductBO::getOrderSn).distinct().collect(Collectors.toList());

		AfterSaleItemQuery afterSaleQuery = new AfterSaleItemQuery();
		afterSaleQuery.setOrderSns(orderSnList);
		afterSaleQuery.setIncludeAfterSaleStatusList(refundCompleteStatusList);
		List<AfterSaleItemOutBO> afterSaleItems = afterSaleService.queryAfterSaleItems(afterSaleQuery);
		if (CollectionUtils.isEmpty(afterSaleItems)) {
			return Maps.newHashMap();
		}
		//订单SKU维度退款金额、运费
		Map<String, List<AfterSaleItemOutBO>> skuCodeAfterSaleMap = afterSaleItems.stream().collect(Collectors.groupingBy(AfterSaleItemOutBO::getSkuCode));
		Set<Map.Entry<String, List<AfterSaleItemOutBO>>> entrySet = skuCodeAfterSaleMap.entrySet();

		Map<String, Tuple> result = Maps.newHashMap();
		for (Map.Entry<String, List<AfterSaleItemOutBO>> entry : entrySet) {
			String skuCode = entry.getKey();
			List<AfterSaleItemOutBO> skuAfterSaleApplies = entry.getValue();

			BigDecimal channelFreightRefundAmount = skuAfterSaleApplies.stream().filter(item -> refundCompleteStatusList.contains(item.getAfterSaleStatus()))
					.map(AfterSaleItemOutBO::getChannelFreightActualRefundAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

			BigDecimal channelRefundAmount = skuAfterSaleApplies.stream().filter(item -> refundCompleteStatusList.contains(item.getAfterSaleStatus()))
					.map(AfterSaleItemOutBO::getChannelActualRefundAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
			Tuple tuple = new Tuple(channelRefundAmount, channelFreightRefundAmount);
			result.put(skuCode, tuple);
		}
		return result;

	}

	@Override
	public OrderBlanketDetailVO orderBlanketDetail(String supplyOrderSn) {
		OrderQueryBO orderQuery = new OrderQueryBO();
		orderQuery.setSupplyTradeSn(supplyOrderSn);
		//获取订单信息
		List<OrderInfoBO> orderInfos = orderService.listOrderInfo(orderQuery);
		if (CollectionUtils.isEmpty(orderInfos)) {
			return null;
		}
		List<OrderInfoBO> splitAfterOrderList = orderInfos.stream().filter(order -> EnumUtils.eq(OrderParentTypeEnum.AFTER_SPLIT, order.getParentType())).collect(Collectors.toList());
		if (CollectionUtils.isEmpty(splitAfterOrderList)) {
			return null;
		}
		OrderInfoBO order = SupplyCollectionUtils.getSingleDataFirst(splitAfterOrderList, OrderInfoBO::new);
		//订单基本信息
		OrderBlanketDetailVO.BaseInfo baseInfo = new OrderBlanketDetailVO.BaseInfo();
		baseInfo.setSupplyTradeSn(order.getSupplyTradeSn());
		baseInfo.setBizTradeSn(order.getBizTradeSn());
		baseInfo.setMchId(order.getMchId());
		baseInfo.setUserId(order.getUserId());
		baseInfo.setCreateTime(order.getCreateTime());
		BusinessConfigVO bizCodeInfo = resourceBusinessConfigAdminClient.getBizCode(order.getShowServerName());
		if (Objects.nonNull(bizCodeInfo)) {
			baseInfo.setServerName(bizCodeInfo.getBizDescribe());
		}
		//订单信息
		List<OrderBlanketDetailVO.OrderInfo> resultOrderInfoList = this.buildBlanketOrderInfo(splitAfterOrderList);
		//运费信息
		this.buildBlanketOrderFreight(orderInfos, resultOrderInfoList);
		//返回结果
		OrderBlanketDetailVO orderBlanketDetail = new OrderBlanketDetailVO();
		orderBlanketDetail.setOrderType(order.getOrderType());
		orderBlanketDetail.setBaseInfo(baseInfo);
		orderBlanketDetail.setOrderInfoList(resultOrderInfoList);
		orderBlanketDetail.setOrderInfoStatistics(this.buildBlanketOrderStatistics(resultOrderInfoList));
		return orderBlanketDetail;
	}

	/**
	 * 组装总单详情-订单信息
	 */
	private List<OrderBlanketDetailVO.OrderInfo> buildBlanketOrderInfo(List<OrderInfoBO> splitAfterOrderList) {
		//订单信息
		List<OrderBlanketDetailVO.OrderInfo> resultOrderInfoList = Lists.newArrayList();
		//key:渠道编码、value:订单信息集合
		Map<String, List<OrderInfoBO>> channelOrderInfoMap = splitAfterOrderList.stream().collect(Collectors.groupingBy(OrderInfoBO::getChannelCode));
		channelOrderInfoMap.forEach((key, value) -> {
			ChannelCodeEnum channelCodeEnum = ChannelCodeEnum.getChannelCodeEnumByCode(key);
			value.forEach(info -> {
				OrderBlanketDetailVO.OrderInfo orderInfo = new OrderBlanketDetailVO.OrderInfo();
				orderInfo.setChannelCode(key);
				if (ObjectUtils.isNotEmpty(channelCodeEnum)) {
					orderInfo.setChannelDesc(channelCodeEnum.getDescribe());
				}
				orderInfo.setOrderSn(info.getOrderSn());
				orderInfo.setOrderParentSn(info.getOrderParentSn());
				orderInfo.setChannelOrderSn(info.getChannelOrderSn());
				orderInfo.setChannelOrderParentSn(info.getChannelOrderParentSn());
				orderInfo.setChannelTradeOrderSn(info.getChannelTradeOrderSn());
				orderInfo.setTotalPlatformPrice(Objects.nonNull(info.getChannelOrderRealityAmount()) ? info.getChannelOrderRealityAmount() : info.getChannelOrderAmount());
				orderInfo.setTotalPlatformSellPrice(info.getOrderAmount());
				//获取退款金额、运费
				AfterSaleItemQuery afterSaleQuery = new AfterSaleItemQuery();
				afterSaleQuery.setOrderSns(Collections.singletonList(info.getOrderSn()));
				afterSaleQuery.setIncludeAfterSaleStatusList(Collections.singletonList(AfterSaleStatusEnum.COMPLETED.getValue()));
				List<AfterSaleItemOutBO> afterSaleItems = afterSaleService.queryAfterSaleItems(afterSaleQuery);
				BigDecimal channelFreightRefundAmount = afterSaleItems.stream().map(AfterSaleItemOutBO::getChannelFreightActualRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
				BigDecimal channelRefundAmount = afterSaleItems.stream().map(AfterSaleItemOutBO::getChannelActualRefundAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

				orderInfo.setChannelRefundAmount(channelRefundAmount);
				orderInfo.setTotalChannelRefundFreight(channelFreightRefundAmount);
				resultOrderInfoList.add(orderInfo);
			});
		});
		return resultOrderInfoList;
	}

	/**
	 * 组装总单详情-运费信息
	 */
	private void buildBlanketOrderFreight(List<OrderInfoBO> orderInfos, List<OrderBlanketDetailVO.OrderInfo> resultOrderInfoList) {
		//原始订单
		List<OrderInfoBO> originalOrderList = orderInfos.stream().filter(o -> EnumUtils.eq(OrderLevelEnum.CHANNEL_MASTER_ORDER, o.getOrderParentSn())).collect(Collectors.toList());
		//key:渠道编码、value:付款运费
		Map<String, BigDecimal> channelPayFreight = originalOrderList.stream().filter(item -> Objects.nonNull(item.getChannelFreightAmount()))
				.collect(Collectors.groupingBy(OrderInfoBO::getChannelCode, Collectors.reducing(BigDecimal.ZERO, OrderInfoBO::getChannelFreightAmount, BigDecimal::add)));

		//key:渠道编码、value:退款运费
		Map<String, BigDecimal> channelRefundFreight = resultOrderInfoList.stream().filter(item -> Objects.nonNull(item.getTotalChannelRefundFreight()))
				.collect(Collectors.groupingBy(OrderBlanketDetailVO.OrderInfo::getChannelCode, Collectors.reducing(BigDecimal.ZERO, OrderBlanketDetailVO.OrderInfo::getTotalChannelRefundFreight, BigDecimal::add)));

		resultOrderInfoList.forEach(item -> {
			item.setTotalChannelFreight(channelPayFreight.getOrDefault(item.getChannelCode(), BigDecimal.ZERO));
			item.setTotalChannelRefundFreight(channelRefundFreight.getOrDefault(item.getChannelCode(), BigDecimal.ZERO));
		});
	}

	/**
	 * 组装总单详情-统计信息
	 */
	private OrderBlanketDetailVO.OrderInfoStatistics buildBlanketOrderStatistics(List<OrderBlanketDetailVO.OrderInfo> resultOrderInfoList) {
		BigDecimal totalPlatformPrice = BigDecimal.ZERO;
		BigDecimal totalPlatformSellPrice = BigDecimal.ZERO;
		BigDecimal totalChannelRefundAmount = BigDecimal.ZERO;
		//统计付款金额、运费以及退款金额、运费
		BigDecimal totalChannelFreight = BigDecimal.ZERO;
		BigDecimal totalChannelRefundFreight = BigDecimal.ZERO;
		//渠道编码Set
		Set<String> channelCodeSet = Sets.newHashSet();
		for (OrderBlanketDetailVO.OrderInfo orderInfo : resultOrderInfoList) {
			totalPlatformPrice = totalPlatformPrice.add(orderInfo.getTotalPlatformPrice());
			totalPlatformSellPrice = totalPlatformSellPrice.add(orderInfo.getTotalPlatformSellPrice());
			totalChannelRefundAmount = totalChannelRefundAmount.add(orderInfo.getChannelRefundAmount());
			if (channelCodeSet.add(orderInfo.getChannelCode())) {
				totalChannelFreight = totalChannelFreight.add(orderInfo.getTotalChannelFreight());
				totalChannelRefundFreight = totalChannelRefundFreight.add(orderInfo.getTotalChannelRefundFreight());
			}
		}
		return new OrderBlanketDetailVO.OrderInfoStatistics(totalChannelFreight, totalChannelRefundFreight,
				totalPlatformSellPrice, totalPlatformPrice, totalChannelRefundAmount);
	}

	@Override
	public List<OrderDeliveryVO> listOrderDelivery(OrderDeliveryDTO orderDelivery) {
		try {
			OrderQueryBO orderQuery = new OrderQueryBO();
			orderQuery.setOrderSnList(orderDelivery.getOrderSnList());
			List<OrderInfoBO> orderInfoList = orderService.listOrderInfo(orderQuery);
			List<OrderInfoBO> shippedOrderList = orderInfoList.stream().filter(item -> OrderStatusEnum.checkLogistics(item.getOrderStatus())).collect(Collectors.toList());

			List<String> orderSnList = shippedOrderList.stream().map(OrderInfoBO::getOrderSn).collect(Collectors.toList());

			List<LogisticQueryParam.ExpressInfo> expressInfo = orderService.getExpressInfo(orderSnList);

			List<OrderDeliveryBO> orderDeliveryList = orderBoundaryClient.queryLogisticInfoList(orderDelivery.getOrderSnList(), shippedOrderList,expressInfo);
			return orderDeliveryList.stream().map(delivery -> {
				List<OrderDeliveryVO.DeliveryInfo> deliveryInfoList = delivery.getDeliveryInfoList().stream().map(info -> {
					List<OrderDeliveryVO.DeliveryInfo.TrackInfo> trackInfoVoList = info.getTrackInfoList().stream().map(s -> {
						OrderDeliveryVO.DeliveryInfo.TrackInfo trackInfo = new OrderDeliveryVO.DeliveryInfo.TrackInfo();
						trackInfo.setTrackContent(s.getTrackContent());
						trackInfo.setTrackOperator(s.getTrackOperator());
						trackInfo.setTrackMsgTime(s.getTrackMsgTime());
						return trackInfo;
					}).collect(Collectors.toList());

					OrderDeliveryVO.DeliveryInfo deliveryInfo = new OrderDeliveryVO.DeliveryInfo();
					deliveryInfo.setDeliveryOrderSn(info.getDeliveryOrderSn());
					deliveryInfo.setDeliveryCarrier(info.getDeliveryCarrier());
					deliveryInfo.setTrackInfoList(trackInfoVoList);
					return deliveryInfo;
				}).collect(Collectors.toList());

				OrderDeliveryVO orderDeliveryView = new OrderDeliveryVO();
				orderDeliveryView.setOrderSn(delivery.getOrderSn());
				orderDeliveryView.setDeliveryInfoList(deliveryInfoList);
				return orderDeliveryView;
			}).collect(Collectors.toList());
		} catch (Exception e) {
			return new ArrayList<>();
		}
	}

	@Override
	public Boolean cancelOrder(OrderCancelDTO orderCancel) {
		OrderStatusCheckBO orderStatusCheck = OrderStatusCheckBO.builder().checkStatusList(Lists.newArrayList(OrderStatusEnum.WAIT_PAY.getValue(),
				OrderStatusEnum.WAIT_SHIP.getValue())).build();
		orderStatusCheck.setOrderSnList(orderCancel.getOrderSnList());
		orderStatusCheck.setSupplyTradeSn(orderCancel.getSupplyTradeSn());
		List<OrderInfoBO> orderInfoList = orderService.checkOrderStatus(orderStatusCheck);

		OrderInfoBO orderInfo = SupplyCollectionUtils.getSingleDataFirst(orderInfoList, OrderInfoBO::new);
		List<String> orderSnList = orderInfoList.stream().map(OrderInfoBO::getOrderSn).collect(Collectors.toList());
		if (EnumUtils.eq(OrderStatusEnum.WAIT_PAY, orderInfo.getOrderStatus())) {
			orderService.updateStatusByOrderSnList(orderSnList, OrderStatusEnum.CANCEL, OrderStatusEnum.WAIT_PAY, OperateSourceConstants.BACKSTAGE, OrderOperateConstants.BACKSTAGE_CANCEL,null);
			supplyChainDelayMessageProducer.channelOrderCancelSend(orderCancel.getSupplyTradeSn(), orderSnList, OrderStatusEnum.WAIT_PAY.getValue());
		} else {
			//待发货状态取消订单
			List<String> collect = orderInfoList.stream().filter(item -> !orderService.channelConfirmCompleted(item)).map(OrderInfoBO::getOrderSn).collect(Collectors.toList());
			CustomAssert.isTrue(CollectionUtils.isEmpty(collect), "暂不支持取消操作,请稍后再试", collect);
			orderService.updateStatusByOrderSnList(orderSnList, OrderStatusEnum.CANCELLING, OrderStatusEnum.WAIT_SHIP, OperateSourceConstants.BACKSTAGE, OrderOperateConstants.BACKSTAGE_CANCEL,null);
			supplyChainMQProducer.cancelOrderApplySalesSend(orderCancel.getSupplyTradeSn(), orderSnList);
		}
		supplyChainMQProducer.orderAlterSend(orderInfo.getSupplyTradeSn(), orderInfo.getServerName());
		return Boolean.TRUE;
	}


	@Override
	public Page<OrderRepairPageVO> pageOfRepair(OrderRepairPageDTO orderRepairPage) {
		if (Objects.nonNull(orderRepairPage.getPreWarningStrategyId())) {
			PreWarningConditionDTO preWarningCondition = preWarningConfigService.getPreWarningCondition(orderRepairPage.getPreWarningStrategyId());
			orderRepairPage.setPreWarningCondition(preWarningCondition);
		}
		Page<OrderRepairPageVO> page = orderRepairService.page(orderRepairPage);
		if (CollUtil.isNotEmpty(page.getRecords())) {
			page.getRecords().forEach(item -> {
				item.setChannelCodeMsg(Optional.ofNullable(ChannelCodeEnum.getChannelCodeEnumByCode(item.getChannelCode())).map(ChannelCodeEnum::getDescribe).orElse(StringPool.EMPTY));
				BusinessConfigVO businessConfig = resourceBusinessConfigAdminClient.getBizCode(item.getShowServerName());
				if (Objects.nonNull(businessConfig)) {
					item.setShowServerName(businessConfig.getBizDescribe());
				}
			});
		}
		return page;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean batchOrderRepair(BatchRepairDTO batchRepair) {
		orderRepairService.statusCheck(batchRepair.getOrderSnList(), Lists.newArrayList(OrderRepairStatusEnum.WAIT_REPAIR, OrderRepairStatusEnum.REPAIR_FAILED));
		OrderStatusCheckBO orderStatusCheck = OrderStatusCheckBO.builder().orderSnList(Lists.newArrayList(batchRepair.getOrderSnList()))
				.checkStatusList(Lists.newArrayList(OrderStatusEnum.FAILURE.getValue())).build();
		orderService.checkOrderStatus(orderStatusCheck);
		// 修改异常订单状态为补单中
		UpdateOrderRepairBO updateObj = UpdateOrderRepairBO.builder().orderSnList(batchRepair.getOrderSnList()).newStatus(OrderRepairStatusEnum.REPAIRING.getValue()).build();
		orderRepairService.updateOrderRepairStatusAndErrorInfo(updateObj);

		String administrator = OperateAuthUtil.getAdministrator();
		List<OperationLogSaveDTO> operationLogSaveList = batchRepair.getOrderSnList().stream().map(item -> OperationLogSaveDTO.builder().logType(OperationLogTypeEnum.ORDER.getValue())
				.bizKey(item).scene(OrderOperateConstants.BACKSTAGE_DO_REPAIR).source(OperateSourceConstants.BACKSTAGE).operator(administrator).build()).collect(Collectors.toList());
		operationLogService.asyncBatchSave(operationLogSaveList);
		// 发送补单消息
		batchRepair.getOrderSnList().forEach(supplyChainMQProducer::sendOrderRepairMessage);
		return Boolean.TRUE;
	}

	@Override
	public OrderRepairDetailVO orderRepairDetail(String orderSn) {
		OrderRepairBO orderRepair = orderRepairService.getByOrderSn(orderSn, false);
		CustomAssert.notNull(orderRepair, "补单数据不存在");
		List<OrderBO> orderList = orderService.list(OrderQueryInBO.builder().returnProduct(Boolean.TRUE).returnConsignee(Boolean.TRUE).orderSnList(Lists.newArrayList(orderSn)).build());
		CustomAssert.notEmpty(orderList, "订单不存在");

		OrderBO order = SupplyCollectionUtils.getSingleDataFirst(orderList, OrderBO::new);
		OrderRepairDetailVO.OrderInfoVO repairOrderInfo = orderConverter.toRepairOrderInfo(orderRepair, order);
		String showServerName = resourceBusinessConfigAdminClient.getBizCode(order.getShowServerName()).getBizDescribe();
		repairOrderInfo.setShowServerName(showServerName);
		List<OrderRepairDetailVO.OrderProductVO> orderRepairDetailProductList = orderConverter.toOrderRepairDetailProductList(order.getOrderProductList());
		OrderRepairDetailVO.OrderConsigneeVO consignee = orderConverter.toOrderRepairDetailConsignee(order.getOrderAddress());
		OrderRepairDetailVO orderRepairDetail = new OrderRepairDetailVO();
		orderRepairDetail.setOrderInfo(repairOrderInfo);
		orderRepairDetail.setOrderProductList(orderRepairDetailProductList);
		orderRepairDetail.setOrderConsignee(consignee);
		return orderRepairDetail;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean batchCloseOrderRepair(BatchCloseDTO batchClose) {
		// 校验补单数据状态
		orderRepairService.statusCheck(batchClose.getOrderSnList(), Lists.newArrayList(OrderRepairStatusEnum.WAIT_REPAIR, OrderRepairStatusEnum.REPAIR_FAILED));
		List<OrderInfoBO> orderInfoList = orderService.checkOrderStatus(OrderStatusCheckBO.builder().orderSnList(batchClose.getOrderSnList()).checkStatusList(Lists.newArrayList(OrderStatusEnum.FAILURE.getValue())).build());
		// 更新补单状态
		UpdateOrderRepairBO updateOrderRepair = UpdateOrderRepairBO.builder().orderSnList(batchClose.getOrderSnList()).newStatus(OrderRepairStatusEnum.CLOSED.getValue()).build();
		orderRepairService.updateOrderRepairStatusAndErrorInfo(updateOrderRepair);

		// 更新订单状态和tag
		orderInfoList.stream().map(item -> {
			UpdateOrderBO updateOrder = UpdateOrderBO.builder().orderStatus(Pair.of(OrderStatusEnum.FAILURE.getValue(), OrderStatusEnum.CANCEL.getValue())).orderSn(item.getOrderSn()).orderTag(item.removeTag(OrderTagEnum.REPAIRING.getValue()))
					.source(OperateSourceConstants.BACKSTAGE).description(OrderOperateConstants.BACKSTAGE_CLOSED_REPAIR_ORDER).build();
			List<Diff> diffs = item.diff(updateOrder).getDiffs();
			updateOrder.setLogChangeItemList(diffs);
			return updateOrder;
		}).forEach(orderService::updateOrderByOrderSn);

		Map<String, String> supplyTradeSnMap = orderInfoList.stream().collect(Collectors.toMap(OrderInfoBO::getSupplyTradeSn, OrderInfoBO::getServerName, (o1, o2) -> o1));
		if (MapUtil.isNotEmpty(supplyTradeSnMap)) {
			supplyTradeSnMap.forEach(supplyChainMQProducer::orderAlterSend);
		}
		return Boolean.TRUE;
	}

	@Override
	public Boolean modifyOrderStatus(OrderStatusUpdateDTO orderStatusUpdate) {
		List<OrderBO> orderList = orderService.list(OrderQueryInBO.builder().orderSnList(Lists.newArrayList(orderStatusUpdate.getOrderSn())).build());
		OrderStatusEnum statusNew = OrderStatusEnum.getOrderSubStatusEnum(orderStatusUpdate.getStatus());
		CustomAssert.notNull(statusNew, "无效的订单状态");
		OrderBO singleData = SupplyCollectionUtils.getSingleData(orderList, "存在多个订单");
		OrderStatusEnum statusOld = OrderStatusEnum.getOrderSubStatusEnum(singleData.getOrderStatus());
		boolean validTransition = OrderStatusEnum.isValidTransition(statusOld, statusNew);
		CustomAssert.isTrue(validTransition, String.format("不支持状态从%s到%s", statusOld.getDescribe(), statusNew.getDescribe()));
		UpdateOrderBO updateOrder = new UpdateOrderBO();
		updateOrder.setOrderSn(orderStatusUpdate.getOrderSn());
		updateOrder.setOrderStatus(Pair.of(singleData.getOrderStatus(), orderStatusUpdate.getStatus()));
		updateOrder.setSource(OperateSourceConstants.BACKSTAGE);
		updateOrder.setDescription(orderStatusUpdate.getRemark());
		updateOrder.setOperatorRemark(orderStatusUpdate.getRemark());
		updateOrder.setLogChangeItemList(singleData.diff(updateOrder).getDiffs());
		return orderService.updateOrderByOrderSn(updateOrder);
	}
}
